﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Keystone;
using MemHack.Util;
using Architecture = Keystone.Architecture;

namespace MemHack.Mem
{
	/// <summary>
	/// 汇编脚本函数定义
	/// </summary>
	/// <param name="symbolOption">符号操作接口</param>
	/// <param name="args">解析到的函数参数</param>
	public delegate void InjectAssemblyFuncHandle(AutoAssemblyScripyContext scriptCtx, params string[] args);

	public interface IAssemblySymbolOption : IDisposable
	{
		bool HasSymbol(string name);

		void PutSymbol(string name, ulong addr);

		ulong GetSymbol(string name);

		void PutGlobalSymbol(string name, ulong addr);

		ulong GetGlobalSymbol(string name);

		void RemoveSymbol(string symbol);

		void RemoveGlobalSymbol(string symbol);

		void ForEach(Action<string, ulong, bool> func);
	}

	public interface IExecuteAssemblyScript
	{
		bool IsEnable();
		void Enable();

		void Restore();
	}

	internal class AssemblyScriptSegment
	{
		public AssemblyScriptSegment(string symbol, string conetnt, bool isEnable)
		{
			Symbol = symbol;
			Conetnt = conetnt;
			IsEnable = isEnable;
		}

		public string Symbol { get; }

		public string Conetnt { get; }

		public bool IsEnable { get; }
	}

	/// <summary>
	/// 汇编脚本符号表管理
	/// </summary>
	public class AssemblyScriptSymbolCotroller : IAssemblySymbolOption
	{
		// 当前存储的符号表
		private Dictionary<string, ulong> mSymbols = new Dictionary<string, ulong>();

		// 全局符号表
		private static Dictionary<string, ulong> GlobalSymbols = new Dictionary<string, ulong>();

		// 汇编关键字
		private HashSet<string> mAssemblyKeywords = new HashSet<string>()
		{
			"mov", "push", "pop", "xchg", "add", "sub", "mul", "div", "and", "or", "xor", "not",
			"jmp", "je", "jne", "jg", "jl", "cmp", "test", "call", "ret", "pushad", "popad",
			"cli", "sti", "cld", "std", "in", "out", "movs", "cmps", "scas", "lods", "stos",
			"fadd", "fsub", "fmul", "fdiv", "mmx", "sse", "avx", "hlt", "int", "iret", "cli", "sti",
			"nop", "lea", "neg", "sbb", "leave", "dword", "qword", "ptr"
		};

		public void Dispose()
		{
			mSymbols.Clear();
			GlobalSymbols.Clear();
		}

		public ulong GetGlobalSymbol(string name)
		{
			if (!GlobalSymbols.ContainsKey(name))
			{
				throw new ExecuteAssemblyException($"未获取到全局符号: {name}");
			}

			return GlobalSymbols[name];
		}

		public ulong GetSymbol(string name)
		{
			if (!mSymbols.ContainsKey(name))
			{
				throw new ExecuteAssemblyException($"未获取到符号: {name}");
			}

			return mSymbols[name];
		}

		private void DetectSymbolFormat(string symbolName)
		{
			if (!Regex.IsMatch(symbolName, @"^[_a-zA-Z]([\w\.\-])*$"))
			{
				throw new ExecuteAssemblyException($"符号名:{symbolName}, 定义不规范");
			}

			if (mAssemblyKeywords.Contains(symbolName))
			{
				throw new ExecuteAssemblyException($"符号名:{symbolName}, 不能是汇编关键字");
			}
		}

		public void PutGlobalSymbol(string name, ulong addr)
		{
			DetectSymbolFormat(name);
			if (GlobalSymbols.ContainsKey(name))
			{
				throw new ExecuteAssemblyException($"存在相同的全局符号: {name}");
			}

			GlobalSymbols[name] = addr;
		}

		public void PutSymbol(string name, ulong addr)
		{
			DetectSymbolFormat(name);
			if (mSymbols.ContainsKey(name))
			{
				throw new ExecuteAssemblyException($"存在相同的符号: {name}");
			}

			mSymbols[name] = addr;
		}

		public bool HasSymbol(string name)
		{
			if (mSymbols.ContainsKey(name) || GlobalSymbols.ContainsKey(name))
			{
				return true;
			}

			return false;
		}

		public void RemoveSymbol(string symbol)
		{
			mSymbols.Remove(symbol);
		}

		public void RemoveGlobalSymbol(string symbol)
		{
			GlobalSymbols.Remove(symbol);
		}

		public void ForEach(Action<string, ulong, bool> func)
		{
			foreach (KeyValuePair<string, ulong> pair in mSymbols)
			{
				func.Invoke(pair.Key, pair.Value, false);
			}
			foreach (KeyValuePair<string, ulong> pair in GlobalSymbols)
			{
				func.Invoke(pair.Key, pair.Value, true);
			}
		}
	}

	public abstract class AutoAssemblyScripyContext
	{
		public MemoryHack MemHack { get; }

		public IAssemblySymbolOption SymbolOption { get; protected set; } = new AssemblyScriptSymbolCotroller();

		public long InjectAddr { get; protected set; }

		public event Action OnEnbaledScript;

		public event Action OnRestoreScript; 

		protected AutoAssemblyScripyContext(MemoryHack memHack)
		{
			MemHack = memHack;
			InitModuleSymbol();
		}

		private void InitModuleSymbol()
		{
			foreach (ProcessModule module in MemHack.Process.Modules)
			{
				int i = 2;
				string name = module.ModuleName;
				// 防止存在相同的模块
				while (SymbolOption.HasSymbol(name))
				{
					name = $"{module.ModuleName}{i++}";
				}
				SymbolOption.PutSymbol(name, (ulong)module.BaseAddress.ToInt64());
			}
		}

		protected void EmitOnEnabledScriptEvent()
		{
			if (OnEnbaledScript != null)
			{
				OnEnbaledScript.Invoke();
				Delegate[] delegates = OnEnbaledScript.GetInvocationList();
				foreach (Delegate action in delegates)
				{
					OnEnbaledScript -= action as Action;
				}
			}
		}

		protected void EmitOnRestoreScriptEvent()
		{
			if (OnRestoreScript != null)
			{
				OnRestoreScript.Invoke();
				Delegate[] delegates = OnRestoreScript.GetInvocationList();
				foreach (Delegate action in delegates)
				{
					OnRestoreScript -= action as Action;
				}
			}
		}
	}

	public class DefaultAutoAssembly : AutoAssemblyScripyContext, IExecuteAssemblyScript, IDisposable
	{
		private readonly Engine engine;

		private bool isEnable = false;

		// 记录对地址进行修改前的字节数组
		private Dictionary<ulong, byte[]> srcBytesMap = new Dictionary<ulong, byte[]>();

		// 对汇编脚本进行的分段处理后的信息
		private List<AssemblyScriptSegment> scriptSegments = new List<AssemblyScriptSegment>(20);

		// 0地址符号
		private readonly string ZeroSymbol = "__ZeroSymbol__";

		public DefaultAutoAssembly(MemoryHack memoryHack, string assemblyScript) : base(memoryHack)
		{
			engine = new Engine(ParseCurrentArchitecture(), ParseProcessMode()){ThrowOnError = true};
			engine.SetOption(OptionType.SYNTAX, (uint) OptionValue.SYNTAX_INTEL);
			engine.ResolveSymbol += Engine_ResolveSymbol;
			SymbolOption.PutSymbol(ZeroSymbol, 0);
			ParseAssemblyScript(assemblyScript);
		}

		// 解析引擎未直接找到的符号
		private bool Engine_ResolveSymbol(string symbol, ref ulong value)
		{
			if (!SymbolOption.HasSymbol(symbol))
			{
				MemHack.Log($"未定义的符号: {symbol}", false);
				return false;
			}

			try
			{
				value = GetSymbol(symbol);
			}
			catch (Exception)
			{
				MemHack.Log($"未定义的符号: {symbol}", false);
				return false;
			}

			return true;
		}

		private ulong GetSymbol(string symbol)
		{
			try
			{
				return SymbolOption.GetSymbol(symbol);
			}
			catch (Exception)
			{
				return SymbolOption.GetGlobalSymbol(symbol);
			}
		}

		private Architecture ParseCurrentArchitecture()
		{
			switch (RuntimeInformation.OSArchitecture)
			{
				case System.Runtime.InteropServices.Architecture.X86:
					return Architecture.X86;
				case System.Runtime.InteropServices.Architecture.X64:
					return Architecture.X86;
				case System.Runtime.InteropServices.Architecture.Arm:
					return Architecture.ARM;
				case System.Runtime.InteropServices.Architecture.Arm64:
					return Architecture.ARM64;
			}

			throw new ExecuteAssemblyException("未能识别当前系统架构");
		}

		private Mode ParseProcessMode()
		{
			Architecture arch = ParseCurrentArchitecture();
			if (arch == Architecture.ARM || arch == Architecture.ARM64)
			{
				return Mode.ARM;
			}

			return MemHack.Is64Bit() ? Mode.X64 : Mode.X32;
		}

		/// <summary>
		/// 解析汇编脚本
		/// </summary>
		/// <param name="script">翻译前的汇编脚本</param>
		private void ParseAssemblyScript(string script)
		{
			StringBuilder sb = new StringBuilder();

			// 根据地址段分割不同的汇编脚本段
			string[] lines = script.Split('\n')
				.Where(line => !string.IsNullOrWhiteSpace(line))
				.Select(line => line.Trim())
				.ToArray();
			string symbol = ZeroSymbol;
			bool isRestore = false;
			sb.Clear();

			foreach (string line in lines)
			{
				string handleLine = line.Contains(";") ? line.Split(';')[0] : line;
				if (string.IsNullOrWhiteSpace(handleLine))
				{
					continue;
				}

				if (Regex.IsMatch(handleLine, @"^\[Restore]$", RegexOptions.IgnoreCase))
				{
					if (sb.Length > 0)
					{
						scriptSegments.Add(new AssemblyScriptSegment(symbol, sb.ToString(), !isRestore));
						sb.Clear();
					}
					symbol = ZeroSymbol;
					isRestore = true;
					continue;
				}

				if (handleLine.EndsWith(":"))
				{
					if (sb.Length > 0)
					{
						scriptSegments.Add(new AssemblyScriptSegment(symbol, sb.ToString(), !isRestore));
						sb.Clear();
					}

					symbol = handleLine.TrimEnd(':');
					continue;
				}

				sb.AppendLine(handleLine);
			}

			if (sb.Length > 0)
			{
				scriptSegments.Add(new AssemblyScriptSegment(symbol, sb.ToString(), !isRestore));
				sb.Clear();
			}

			// ExtensionFunc.LogToConsole(scriptSegments);
		}

		/// <summary>
		/// 执行汇编脚本
		/// </summary>
		/// <param name="isEnable">是否处于启用模式</param>
		private void ExecuteAssemblyScript(bool isEnable)
		{
			StringBuilder sb = new StringBuilder();
			int index = 0;
			while (index < scriptSegments.Count)
			{
				AssemblyScriptSegment scriptSegment = scriptSegments[index];
				if (scriptSegment.IsEnable != isEnable)
				{
					index += 1;
					continue;
				}
				// 解析开始的符号不能找不到
				if (!SymbolOption.HasSymbol(scriptSegment.Symbol))
				{
					throw new ExecuteAssemblyException($"未找到符号: {scriptSegment.Symbol}");
				}

				InjectAddr = (long) GetSymbol(scriptSegment.Symbol);
				// 开始执行其中的自定义脚本函数
				scriptSegment.Conetnt.Split('\n')
					.Where(line => !string.IsNullOrWhiteSpace(line))
					.Select(line => AssemblyScriptRegister.ParseAssemblyScriptLine(this, line.Trim()))
					.Where(line => !string.IsNullOrWhiteSpace(line))
					.ToList()
					.ForEach(line =>
					{
						if (Regex.IsMatch(line, @"^(j|call).*$", RegexOptions.IgnoreCase))
						{
							SymbolOption.ForEach((name, val, _) =>
							{
								line = line.Replace(name, $"0x{val:X}");
							});
						}
						sb.AppendLine(line);
					});

				index += 1;
				// 连带上后面找不到符号(即原始标记)的段
				while (index < scriptSegments.Count && !SymbolOption.HasSymbol(scriptSegments[index].Symbol) &&
				       scriptSegments[index].IsEnable == scriptSegment.IsEnable)
				{
					sb.AppendLine($"{scriptSegments[index].Symbol}:");
					scriptSegments[index].Conetnt.Split('\n')
						.Where(line => !string.IsNullOrWhiteSpace(line))
						.Select(line => AssemblyScriptRegister.ParseAssemblyScriptLine(this, line.Trim()))
						.Where(line => !string.IsNullOrWhiteSpace(line))
						.ToList()
						.ForEach(line =>
						{
							if (Regex.IsMatch(line, @"^(j|call).*$", RegexOptions.IgnoreCase))
							{
								SymbolOption.ForEach((name, val, _) =>
								{
									line = line.Replace(name, $"0x{val:X}");
								});
							}
							sb.AppendLine(line);
						});
					index += 1;
				}
				// 执行脚本
				if (sb.Length > 0)
				{
					try
					{
						EncodedData encodedData = engine.Assemble(sb.ToString(), (ulong)InjectAddr);
						engine.Assemble(sb.ToString(), (ulong)InjectAddr);
						if (!srcBytesMap.ContainsKey((ulong)InjectAddr))
						{
							srcBytesMap.Add((ulong)InjectAddr, MemHack.ReadBytes(InjectAddr, encodedData.Buffer.Length));
						}
						MemHack.WriteBytes(InjectAddr, encodedData.Buffer);
						MemHack.Log($"地址段: {InjectAddr:X}, 语句:{Environment.NewLine}{sb}, 编译结果: {encodedData.Buffer.ToHexStr()}");
					}
					catch (Exception e)
					{
						throw new ExecuteAssemblyException($"翻译汇编[{sb}]失败: {e.Message}");
					}
					sb.Clear();
				}
			}
		}

		public bool IsEnable() => isEnable;

		public void Enable()
		{
			if (isEnable)
			{
				throw new ExecuteAssemblyException("当前自动汇编已经开启");
			}

			try
			{
				ExecuteAssemblyScript(true);
				this.isEnable = true;
				EmitOnEnabledScriptEvent();
			}
			catch (Exception e)
			{
				throw new ExecuteAssemblyException($"启动汇编脚本失败: {e.Message}", e);
			}
		}

		public void Restore()
		{
			if (isEnable)
			{
				foreach (var pair in srcBytesMap)
				{
					MemHack.WriteBytes((long) pair.Key, pair.Value);
				}
				ExecuteAssemblyScript(false);
				srcBytesMap.Clear();
				this.isEnable = false;
				EmitOnRestoreScriptEvent();
			}
		}

		public void Dispose()
		{
			engine?.Dispose();
			SymbolOption?.Dispose();
		}
	}

	internal class AsssemblyFuncHandler
	{
		public string FuncName { get;}

		public Regex Pattern => ParseFuncNameToRegex();

		public InjectAssemblyFuncHandle Handler { get; }

		public int FuncArgsNum { get; }

		public AsssemblyFuncHandler(string funcName, InjectAssemblyFuncHandle handler, int funcArgsNum)
		{
			FuncName = funcName;
			Handler = handler;
			FuncArgsNum = funcArgsNum;
		}

		private Regex ParseFuncNameToRegex()
		{
			StringBuilder sb = new StringBuilder($@"^{FuncName}[(]");
			for (uint i = 0; i < FuncArgsNum; i++)
			{
				sb.Append($@"\s*([\w\s\.\-]+)\s*,");
			}

			string pattern = sb.ToString().TrimEnd(',') + "[)]$";
			return new Regex(pattern);
		}
	}

	public static class AssemblyScriptRegister
	{
		private static LinkedList<AsssemblyFuncHandler> assemblyFuncHandlers = new LinkedList<AsssemblyFuncHandler>();

		static AssemblyScriptRegister()
		{
			RegisterAsssemblyScriptHandler("label", 2, DefaultAssemblyScriptFuncInject.Label);
			RegisterAsssemblyScriptHandler("labelCalc", 3, DefaultAssemblyScriptFuncInject.LabelCalc);
			RegisterAsssemblyScriptHandler("aobScan", 2, DefaultAssemblyScriptFuncInject.AobScan);
			RegisterAsssemblyScriptHandler("alloc", 2, DefaultAssemblyScriptFuncInject.Alloc);
			RegisterAsssemblyScriptHandler("dealloc", 1, DefaultAssemblyScriptFuncInject.DeAlloc);
			RegisterAsssemblyScriptHandler("aobModuleScan", 3, DefaultAssemblyScriptFuncInject.AobModuleScan);
			RegisterAsssemblyScriptHandler("registerGlobalSymbol", 1, DefaultAssemblyScriptFuncInject.AobModuleScan);
			RegisterAsssemblyScriptHandler("createThread", 1, DefaultAssemblyScriptFuncInject.CreateThread);
			RegisterAsssemblyScriptHandler("funcModuleScan", 3, DefaultAssemblyScriptFuncInject.FuncModuleScan);
		}

		/// <summary>
		/// 注册一个自定义汇编脚本函数
		/// </summary>
		/// <param name="injectFuncName">要注入的函数名</param>
		/// <param name="funcArgNum">函数参数个数</param>
		/// <param name="handle">解析该函数的自定义实现逻辑</param>
		public static void RegisterAsssemblyScriptHandler(string injectFuncName, uint funcArgNum, InjectAssemblyFuncHandle handle)
			=> assemblyFuncHandlers.AddLast(new AsssemblyFuncHandler(injectFuncName, handle, (int)funcArgNum));

		/// <summary>
		/// 解析汇编脚本中的一行
		/// </summary>
		/// <param name="ctx">汇编脚本上下文</param>
		/// <param name="line">当前行</param>
		/// <returns>解析后的结果</returns>
		internal static string ParseAssemblyScriptLine(AutoAssemblyScripyContext ctx, string line)
		{
			if (string.IsNullOrWhiteSpace(line))
			{
				return string.Empty;
			}

			foreach (AsssemblyFuncHandler assemblyFuncHandler in assemblyFuncHandlers)
			{
				Match match = assemblyFuncHandler.Pattern.Match(line);
				if (match.Success)
				{
					if (match.Groups.Count != assemblyFuncHandler.FuncArgsNum + 1)
					{
						throw new ExecuteAssemblyException(
							$"{assemblyFuncHandler.FuncName}的方法参数个数应为{assemblyFuncHandler.FuncArgsNum}");
					}

					string[] args = new string[assemblyFuncHandler.FuncArgsNum];
					for (var i = 0; i < args.Length; i++)
					{
						args[i] = match.Groups[i + 1].Value.Trim();
					}
					assemblyFuncHandler.Handler?.Invoke(ctx, args);
					return string.Empty;
				}
			}

			return line.Trim();
		}
	}

	internal static class DefaultAssemblyScriptFuncInject
	{
		/// <summary>
		/// 定义一个符号
		/// </summary>
		/// <param name="scriptCtx">上下文</param>
		/// <param name="args">参数</param>
		public static void Label(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			string label = args[0];
			string addrStr = args[2];
			ulong addr;
			if (!ulong.TryParse(addrStr, out addr))
			{
				try
				{
					addr = Convert.ToUInt64(addrStr, 16);
				}
				catch (Exception)
				{
					throw new ExecuteAssemblyException($"label的第二个参数address[{addrStr}]必须是十进制或十六进制");
				}
			}
			scriptCtx.SymbolOption.PutSymbol(label, addr);
			scriptCtx.OnRestoreScript += () => scriptCtx.SymbolOption.RemoveSymbol(label);
		}

		/// <summary>
		/// 对原符号执行的地址进行偏移，赋值给新的符号
		/// </summary>
		/// <param name="scriptCtx">脚本上下文</param>
		/// <param name="args">参数</param>
		public static void LabelCalc(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			if (args == null || args.Length != 3)
			{
				throw new ExecuteAssemblyException("labelCalc：labelCalc(newLabel, oldLabel, offset)");
			}

			string newLabel = args[0];
			ulong oldAddr = GetSymbol(scriptCtx.SymbolOption, args[1]);
			string offsetStr = args[2];
			ulong offset;

			if (scriptCtx.SymbolOption.HasSymbol(newLabel))
			{
				throw new ExecuteAssemblyException($"已经存在相同的符号: {newLabel}: {GetSymbol(scriptCtx.SymbolOption, newLabel):X}");
			}

			int flag = offsetStr.StartsWith("-") ? -1 : 1;
			if (flag < 0)
			{
				offsetStr = offsetStr.TrimStart('-');
			}
			if (!ulong.TryParse(offsetStr, out offset))
			{
				try
				{
					offset = Convert.ToUInt64(offsetStr, 16);
				}
				catch (Exception)
				{
					throw new ExecuteAssemblyException($"labelCalc的第三个参数offset[{args[2]}]必须是十进制或十六进制");
				}
			}
			scriptCtx.SymbolOption.PutSymbol(newLabel, flag < 0 ? oldAddr - offset : oldAddr + offset);
			scriptCtx.OnRestoreScript += () => scriptCtx.SymbolOption.RemoveSymbol(newLabel);
			scriptCtx.MemHack.Log($"执行LabelCalc成功, {newLabel}: {(flag < 0 ? oldAddr - offset : oldAddr + offset):X}");
		}

		/// <summary>
		/// 分配虚拟内存
		/// </summary>
		/// <param name="scriptCtx">脚本上下文</param>
		/// <param name="args">参数</param>
		public static void Alloc(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			string label = args[0];
			string sizeStr = args[1];

			int size;
			if (!int.TryParse(sizeStr, out size))
			{
				throw new ExecuteAssemblyException("Alloc函数的第二参数需为十进制数字，表示需要分配的内存大小");
			}

			long addr = scriptCtx.MemHack.AllocVirtualMem((uint) size);
			scriptCtx.SymbolOption.PutSymbol(label, (ulong) addr);
			scriptCtx.MemHack.Log($"Alloc执行成功, {label}:{size}");
		}

		/// <summary>
		/// 释放虚拟内存
		/// </summary>
		/// <param name="scriptCtx">脚本上下文</param>
		/// <param name="args">函数参数</param>
		public static void DeAlloc(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			string label = args[0];
			var addr = GetSymbol(scriptCtx.SymbolOption, label);
			scriptCtx.MemHack.FreeVirtualMem((long) addr);
			scriptCtx.SymbolOption.RemoveSymbol(label);
			scriptCtx.MemHack.Log($"DeAlloc执行成功, {label}");
		}

		/// <summary>
		/// 获取指定模块中的函数地址
		/// </summary>
		/// <param name="scriptCtx">上下文</param>
		/// <param name="args">函数参数</param>
		public static void FuncModuleScan(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			string label = args[0];
			string moduleName = args[1];
			string funcName = args[2];

			ProcessModule[] modules = scriptCtx.MemHack.FindModule(moduleName, true);
			if (modules == null || modules.Length == 0)
			{
				throw new ExecuteAssemblyException($"未找到模块: {moduleName}");
			}

			foreach (ProcessModule module in modules)
			{
				IntPtr addr = NativeCall.GetProcAddress(module.BaseAddress, funcName);
				if (addr != IntPtr.Zero)
				{
					scriptCtx.SymbolOption.PutSymbol(label, (ulong) addr.ToInt64());
					scriptCtx.OnRestoreScript += () => scriptCtx.SymbolOption.RemoveSymbol(label);
					scriptCtx.MemHack.Log($"成功执行FuncModuleScan, {label}:{addr.ToInt64():X}");
					return;
				}
			}

			throw new ExecuteAssemblyException($"未在模块:{moduleName}中找到函数:{funcName}");
		}

		/// <summary>
		/// 注册全局符号
		/// </summary>
		/// <param name="scriptCtx">上下文</param>
		/// <param name="args">参数</param>
		public static void RegisterGlobalSymbol(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			string label = args[0];
			ulong val = scriptCtx.SymbolOption.GetSymbol(label);
			scriptCtx.SymbolOption.PutGlobalSymbol(label, val);
			scriptCtx.OnRestoreScript += () => scriptCtx.SymbolOption.RemoveGlobalSymbol(label);
			scriptCtx.MemHack.Log($"RegisterGlobalSymbolc执行成功, {label}:{val:X}");
		}

		/// <summary>
		/// 创建远程线程
		/// </summary>
		/// <param name="scriptCtx">脚本上下文</param>
		/// <param name="args">脚本参数</param>
		public static void CreateThread(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			string label = args[0];
			ulong addr = GetSymbol(scriptCtx.SymbolOption, label);
			scriptCtx.OnEnbaledScript += () =>
			{
				int res = NativeCall.CreateRemoteThread(scriptCtx.MemHack.Process.Handle, 0, 0,
					new IntPtr((long)addr), IntPtr.Zero, 0, 0);
				if (res != 0)
				{
					scriptCtx.MemHack.Log($"CreateThread执行成功，地址:{addr:X}");
					return;
				}
				scriptCtx.MemHack.Log($"CreateThread执行失败，地址:{addr:X}", false);
			};
		}

		/// <summary>
		/// 汇编特征码扫描
		/// </summary>
		/// <param name="symbolOption">脚本上下文</param>
		/// <param name="args">函数参数</param>
		public static void AobScan(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			if (args == null || args.Length != 2 )
			{
				throw new ExecuteAssemblyException("aobScan参数应为：aobScan(label, byteArray)");
			}
			string label = args[0];
			string bytesStr = args[1];
			byte[] bytes;
			try
			{
				bytes = MemUtil.HexBytesStrToArr(bytesStr);
			}
			catch (Exception e)
			{
				throw new ExecuteAssemblyException(e.Message, e);
			}

			long[] addrs = scriptCtx.MemHack.SearchBytes(bytes);
			if (addrs == null || addrs.Length == 0)
			{
				throw new ExecuteAssemblyException($"未搜索到目标字节: [{bytesStr}]");
			}
			scriptCtx.SymbolOption.PutSymbol(label, (ulong) addrs[0]);
			scriptCtx.OnRestoreScript += () => scriptCtx.SymbolOption.RemoveSymbol(label);
			scriptCtx.MemHack.Log($"执行AobScan成功, 共搜索{bytesStr}到{addrs.Length}个地址,采用第一个:{addrs[0]:X}");
		}

		/// <summary>
		/// 汇编特征码扫描指定模块
		/// </summary>
		/// <param name="symbolOption">脚本上下文</param>
		/// <param name="args">函数参数</param>
		public static void AobModuleScan(AutoAssemblyScripyContext scriptCtx, params string[] args)
		{
			if (args == null || args.Length != 3)
			{
				throw new ExecuteAssemblyException("aobModuleScan参数应为：aobModuleScan(label, moduleName, byteArray)");
			}
			string label = args[0];
			string moduleName = args[1];
			string bytesStr = args[2];

			ProcessModule[] modules = scriptCtx.MemHack.FindModule(moduleName);
			if (modules == null || modules.Length == 0)
			{
				throw new ExecuteAssemblyException($"未找到模块：{moduleName}");
			}

			byte[] bytes;
			try
			{
				bytes = MemUtil.HexBytesStrToArr(bytesStr);
			}
			catch (Exception e)
			{
				throw new ExecuteAssemblyException(e.Message, e);
			}

			foreach (ProcessModule module in modules)
			{
				long[] addrs = scriptCtx.MemHack.SearchBytes(bytes, (ulong)module.BaseAddress.ToInt64(),
					(ulong)IntPtr.Add(module.BaseAddress, module.ModuleMemorySize).ToInt64());
				if (addrs != null && addrs.Length > 0)
				{
					scriptCtx.SymbolOption.PutSymbol(label, (ulong)addrs[0]);
					scriptCtx.OnRestoreScript += () => scriptCtx.SymbolOption.RemoveSymbol(label);
					scriptCtx.MemHack.Log($"执行AobModuleScan成功, 搜索{bytesStr}[{moduleName}]成功,采用第一个:{addrs[0]:X}");
					return;
				}
			}
			throw new ExecuteAssemblyException($"未在模块[{moduleName}]中搜索到目标字节: [{bytesStr}]");
		}

		private static ulong GetSymbol(IAssemblySymbolOption symbolOption, string symbol)
		{
			try
			{
				return symbolOption.GetSymbol(symbol);
			}
			catch (Exception)
			{
				return symbolOption.GetGlobalSymbol(symbol);
			}
		}
	}

	public class ExecuteAssemblyException : Exception
	{
		public ExecuteAssemblyException(string msg) : base(msg)
		{

		}

		public ExecuteAssemblyException(string msg, Exception innerException) : base(msg, innerException)
		{

		}
	}
}
